﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using X3DXNA.core.CustomNodes;
using X3DXNA.interfaces;
using X3DXNA.core.Boundings;
using X3DXNA.services;
using X3DXNA.X3DSchema;
using X3DXNA.utils;

namespace X3DXNA.basicModels
{
    public class basicCylinderModel : IGeometry
    {
        Game game;
        Model cylinder;
        Matrix world;
        Matrix basicTransformation;
        myBasicEffect basicEffect;
        MyBoundingBox modelBasicBoundingBox;

        public Matrix World { get { return world; } set { world = value; } }
        public String DEF { get; set; }
        public Matrix getBasicTransformation { get { return basicTransformation; } }

        public basicCylinderModel(String DEF, Game game, float radius, float height, Matrix initialTransformation)
        {
            this.DEF = DEF;
            this.game = game;
            //Carico il modello.
            cylinder = game.Content.Load<Model>("BasicModels/cylinder");
            //Traggo il basicEffect dai servizi.
            this.basicEffect = (myBasicEffect)game.Services.GetService(typeof(myBasicEffect));
            //Calcolo la matrice di trasformazione dal "radius" e dalla "height" dell'X3D.
            basicTransformation = Matrix.CreateScale(new Vector3(radius, height, radius));
            //Applico la trasformazione del "size" alla trasformazione iniziale;
            world = basicTransformation * initialTransformation;
            //Calcolo la boundingBox di base per questo modello...
            modelBasicBoundingBox = new MyBoundingBox(new BoundingBox(new Vector3(-1f, -0.5f, -1f), new Vector3(1f, 0.5f, 1f)));
            //...e la trasformo, in base alla world definitiva.
            modelBasicBoundingBox.tranformBounding(world);

            cylinder.Meshes[0].MeshParts[0].Effect = basicEffect.getBasicEffect;
            ((BasicEffect)cylinder.Meshes[0].MeshParts[0].Effect).World = world;
        }

        public void draw()
        {
            cylinder.Meshes[0].Draw();
        }

        /// <summary>
        /// Ritorna la boundig box per il modello. ATTENZIONE, se l'oggetto è dinamico, andrà ricalcolata ad ogni update.
        /// </summary>
        /// <returns>La IBounding per questo modello.</returns>
        public IBounding retrieveBounding()
        {
            return modelBasicBoundingBox;
        }

        public Vector3[] getTriangleVertices()
        {
            return (Vector3[])((Dictionary<string, object>)cylinder.Tag)["Vertices"];
        }

        public void applyWorldTransformation(Matrix transformation) { }

        #region Public Static Builder

        public static basicCylinderModel getNewBasicCylinderModel(Game game, Cylinder cylinder, Matrix initialTransformation)
        {
            String DEF = "Default Box";
            float radius = 1;
            float height = 2;

            if (cylinder.DEF != null)
                DEF = cylinder.DEF;
            if (cylinder.radius != null)
                radius = utility.stringToFloat(cylinder.radius);
            if (cylinder.height != null)
                height = utility.stringToFloat(cylinder.height);

            return new basicCylinderModel(DEF, game, radius, height, initialTransformation);
        }

        #endregion

    }
}
